package com.example.myapplicationndk.aidl;


import android.app.Service;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.util.Log;

import androidx.annotation.Nullable;

import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicBoolean;


public class MyService extends Service {


    public static final String TAG = "MyService";

// CopyWriteArrayList支持并发读/写
// AIDL方法是在服务端的Binder线程池中执行的，
// 因此当多个客户端同时连接时，会存在多个线程同时访问的情形
// 类似的还有ConcurrentHashMap

    private AtomicBoolean mIsServiceDestoryed = new AtomicBoolean(false);
    /**
     * 书籍列表
     */
    private CopyOnWriteArrayList<Book> mBookList = new CopyOnWriteArrayList<Book>();


    private RemoteCallbackList<INewBookArrivedListener> mListenerList = new RemoteCallbackList<INewBookArrivedListener>();

    @Override
    public void onCreate() {
        super.onCreate();
        mBookList.add(new Book(1, "Android"));
        mBookList.add(new Book(2, "Ios"));
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        // 权限验证
        Log.d("binder", intent.toString());
        int check = checkCallingOrSelfPermission("com.example.myapplicationndk.permission.ACCESS_BOOK_SERVICE");
        if (check == PackageManager.PERMISSION_DENIED) {
            Log.d("binder", "no");
            return null;
        }
        Log.d("binder", "yes");
        return mBinder;
    }


    private Binder mBinder = new IBookManager.Stub() {


        @Override
        public List<Book> getBookList() throws RemoteException {
            return mBookList;
        }

        @Override
        public void addBook(Book book) throws RemoteException {
            mBookList.add(book);
        }

        @Override
        public void registerListener(INewBookArrivedListener listener) throws RemoteException {
            mListenerList.register(listener);

            final int N = mListenerList.beginBroadcast();
            mListenerList.finishBroadcast();
        }

        @Override
        public void unregisterListener(INewBookArrivedListener listener) throws RemoteException {
            mListenerList.unregister(listener);
            final int N = mListenerList.beginBroadcast();
            mListenerList.finishBroadcast();
        }
    };

    private void onNewBookArrived(Book book) throws RemoteException {
        mBookList.add(book);
        final int N = mListenerList.beginBroadcast();
        for (int i = 0; i < N; i++) {
            INewBookArrivedListener l = mListenerList.getBroadcastItem(i);
            if (l != null) {
                try {
                    l.onNewBookArrived(book);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        }
        mListenerList.finishBroadcast();
    }

    private class ServiceWorker implements Runnable {
        @Override
        public void run() {
            // do background processing here.....
            while (!mIsServiceDestoryed.get()) {
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                int bookId = mBookList.size() + 1;
                Book newBook = new Book(bookId, "new book#" + bookId);
                try {
                    onNewBookArrived(newBook);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        }
    }


    @Override
    public void onDestroy() {
        mIsServiceDestoryed.set(true);
        super.onDestroy();
    }

}